home *** CD-ROM | disk | FTP | other *** search
/ Best of Shareware / Best of PC Windows Shareware 1.0 - Wayzata Technology (7111) (1993).iso / mac / ZIPPED / DOS / GRAPHICS / LISS151.ZIP / LISSSRC.ZIP / OUTPUT.C < prev    next >
C/C++ Source or Header  |  1992-04-21  |  37KB  |  1,079 lines

  1. /* ***********************
  2.     OUTPUT.C
  3.  
  4.       This program displays spherical Lissajous figures and writes a
  5.       data file in either Vivid, Persistence of Vision (PoV), or Connect
  6.       the Dots Smoother (CTDS) format.  It also outputs a 'raw' format
  7.       with just the (x,y,z) of each point.
  8.  
  9.       Program originally written by Dan Farmer using algorithms from
  10.       Clifford Pickover.  Converted from QuickBasic to C by Aaron C. Caba.
  11.       See Scientific American January 1991 and Omni February 1990 for
  12.       excellent examples by Pickover.
  13.  
  14. History:
  15.  
  16.  Version 1.51:
  17.     04/14/92 ACC Adjust camera positioning so it is WYSIWYG with the display
  18.     04/06/92 ACC Incorporate Dan's PoV V. 1.0 syntax and test it.
  19.                  Put statistics output into a separate function
  20.     04/03/92 DMF Changed PoV output for version 1.0 syntax.  (Untested.)
  21.  
  22.  Version 1.5:
  23.     03/10/92 ACC Do some cosmetic fixes
  24.     03/09/92 ACC found bug in sort_index:  changed *count++ to (*count)++
  25.  
  26.  Version 1.4:
  27.     02/11/92 ACC Actually get algo_period to spit out the correct
  28.                  answer, now ctds_sort works 
  29.     01/13/92 ACC Finish algo_period (and there was much rejoycing) (Yeah!)
  30.     01/12/92 ACC Add 'smooth' Vivid output
  31.     01/07/92 ACC Change all scatered calls to 'exit()' to error_fn.
  32.     01/06/92 ACC Add raw output.
  33.     12/21/91 ACC Write these _beautiful_ output functions.
  34.  
  35.  
  36.  *************************/
  37.  
  38. #include "output.h"     /* function prototypes                  */
  39.  
  40. #ifdef DEBUG
  41. unsigned long debug;
  42. #endif
  43.  
  44. /* Procedure to choose which output format is desired */
  45. void output(struct queue_type queue[], int index[], int num_sph, char *data[])
  46. {
  47.     char ch;
  48.     int ch_ok=FALSE;
  49.  
  50.     setactivepage(1);   /* save page #0 so it dosen't have to be re-drawn */
  51.     setvisualpage(1);   /* choose page #1 to draw on */
  52.     clearviewport();
  53.  
  54.  
  55.     disp_text(5,0,"Script file type:  [P]oV  [V]ivid  [C]TDS  [R]aw",EGA_DARKGRAY);
  56.     disp_message("Press <ESC> to cancel");
  57.     while (!ch_ok) {
  58.         ch=getch();
  59.         ch_ok=TRUE;
  60.         switch(ch) {
  61.             case 'p':
  62.             case 'P':
  63.                 choose_pv_output(queue, index, num_sph, data);
  64.                 break;
  65.             case 'v':
  66.             case 'V':
  67.                 choose_v_output(queue, index, num_sph, data);
  68.                 break;
  69.             case 'c':
  70.             case 'C':
  71.                 ctds_output(queue, num_sph, data);
  72.                 break;
  73.             case 'r':
  74.             case 'R':
  75.                 raw_output(queue, index, num_sph, data);
  76.                 break;
  77.             case ESC:
  78.             case RETURN: break;
  79.             default:
  80.                 ch_ok=FALSE;
  81.                 break;
  82.         }
  83.     }
  84.     setactivepage(0);   /* return to gui-like screen */
  85.     setvisualpage(0);
  86. }
  87.  
  88.  
  89. void choose_pv_output(struct queue_type queue[], int index[],
  90.                      int num_sph, char *data[])
  91. {
  92.     int ch_ok=FALSE;
  93.     char ch;
  94.     disp_text(8,1,"PoV file type:   Version [0].5ß   Version [1].0 ",EGA_DARKGRAY);
  95.     while (!ch_ok) {
  96.         ch=getch();
  97.         ch_ok=TRUE;
  98.         switch(ch) {
  99.             case '0':
  100.                 pv_output(queue, index, num_sph, data, POV_VER_05);
  101.                 break;
  102.             case '1':
  103.                 pv_output(queue, index, num_sph, data, POV_VER_10);
  104.             case RETURN:
  105.             case ESC:
  106.                 break;
  107.             default:
  108.                 ch_ok=FALSE;
  109.                 break;
  110.         }
  111.     }
  112. } /* end choose_pv_output */
  113.  
  114.  
  115. void choose_v_output(struct queue_type queue[], int index[],
  116.                      int num_sph, char *data[])
  117. {
  118.     int ch_ok=FALSE;
  119.     char ch;
  120.     disp_text(8,1,"Vivid file type:  [S]mooth  [B]eaded",EGA_DARKGRAY);
  121.     while (!ch_ok) {
  122.         ch=getch();
  123.         ch_ok=TRUE;
  124.         switch(ch) {
  125.             case 's':
  126.             case 'S':
  127.                 smooth_v_output(queue, index, num_sph, data);
  128.                 break;
  129.             case 'b':
  130.             case 'B':
  131.                 v_output(queue, index, num_sph, data);
  132.             case RETURN:
  133.             case ESC:
  134.                 break;
  135.             default:
  136.                 ch_ok=FALSE;
  137.                 break;
  138.         }
  139.     }
  140. } /* end choose_v_output */
  141.  
  142.  
  143. void raw_output(struct queue_type queue[], int index[],
  144.                 int num_sph, char *data[])
  145. {
  146.     int ch_ok=FALSE;
  147.     char ch;
  148.  
  149.     disp_text(8,1,"Sort data on:  View-[A]xis or [C]TDS sytle",EGA_DARKGRAY);
  150.     while (!ch_ok) {
  151.         ch=getch();
  152.         ch_ok=TRUE;
  153.         switch(ch) {
  154.             case 'a':
  155.             case 'A':
  156.                 write_raw_spheres(queue, index, num_sph);
  157.                 break;
  158.             case 'c':
  159.             case 'C':
  160.                 write_craw_spheres(queue, num_sph, data);
  161.             case RETURN:
  162.             case ESC:
  163.                 break;
  164.             default:
  165.                 ch_ok=FALSE;
  166.                 break;
  167.         }
  168.     }
  169. } /* end raw_output */
  170.  
  171.  
  172. void write_raw_spheres(struct queue_type queue[], int index[], int num_sph)
  173. {
  174.     int i;
  175.     char name[13],  /* name of file to write to */
  176.          msg[80];
  177.     FILE *stream;   /* file pointer to 'name'   */
  178.  
  179.     /* have user input the name of the data file to use         */
  180.     strcpy(name,input_name(".RAW"));
  181.     if (strlen(name) == 0) return;  /* bail out back to main menu   */
  182.  
  183.     /* open the data file */
  184.     if((stream=fopen(name,"wt")) == NULL)
  185.         error_fn(EFOPEN,name);
  186.     else {
  187.         /* write the data */
  188.         sprintf(msg,"Writing %s...",name);
  189.         disp_message(msg);
  190.         for(i=0; i<num_sph; i++)
  191.             fprintf(stream,"%11f  %11f  %11f\n",
  192.                     queue[index[i]].x,queue[index[i]].y,queue[index[i]].z);
  193.  
  194.         /* close the file */
  195.         if(fclose(stream)==EOF)
  196.             error_fn(EFCLOSE,name);
  197.         else {
  198.             sprintf(msg,"RAW data file %s sucessfully written.  Any key to continue:",name);
  199.             disp_message(msg);
  200.             getch();
  201.         }
  202.     }
  203. } /* end write_raw_spheres */
  204.  
  205.  
  206. void write_craw_spheres(struct queue_type queue[], int num_sph, char *data[])
  207. {
  208.     struct pnode far *root=NULL;
  209.     char name[13],      /* name of data file            */
  210.          msg[80];       /* temp string                  */
  211.     FILE *stream;       /* the file handel              */
  212.  
  213.     /* have user input the name of the data file to use         */
  214.     strcpy(name,input_name(".RAW"));
  215.     if (strlen(name) == 0) return;  /* bail out back to main menu   */
  216.  
  217.     root=ctds_sort(root, num_sph, algo_period(data));
  218.  
  219.     /* open the data file */
  220.     if((stream=fopen(name,"wt")) == NULL)
  221.         error_fn(EFOPEN,name);
  222.     else {
  223.         /* write the data */
  224.         sprintf(msg,"Writing %s...",name);
  225.         disp_message(msg);
  226.         ftreeprint(stream, queue, root, 0, NULL);
  227.  
  228.         /* close the file */
  229.         if(fclose(stream)==EOF)
  230.             error_fn(EFCLOSE,name);
  231.         else {
  232.             sprintf(msg,"RAW data file %s sucessfully written.  Any key to continue:",name);
  233.             disp_message(msg);
  234.             getch();
  235.         }
  236.     }
  237.     free_tree(root);
  238. } /* end write_craw_spheres */
  239.  
  240.  
  241. /* This function determines the period of the algorithm
  242.    based on the a,b, and exponent variables. */
  243. double algo_period(char *data[])  
  244. {
  245.     double per,
  246.            x_per,y_per,z_per,   /* in units of PI */
  247.            a,b,
  248.            temp;
  249.     int exp_x, exp_y, exp_z;
  250.  
  251.     disp_message("Finding period...");
  252.     exp_x=atoi(data[EXPONENT_X]);
  253.     exp_y=atoi(data[EXPONENT_Y]);
  254.     exp_z=atoi(data[EXPONENT_Z]);
  255.     a=atof(data[A]);
  256.     b=atof(data[B]);
  257.  
  258.     per=gcd(a,b);
  259.     switch(atoi(data[ALGO])) {
  260.         case 1:
  261.         case 2:
  262.         case 3:
  263.             x_per=y_per=PI;
  264.             if(even(exp_z)) z_per=PI;
  265.             else z_per=2.0*PI;
  266.  
  267.             x_per = PI/per;
  268.             y_per = PI/per;
  269.             z_per /= a;
  270.             break;
  271.         case 4:
  272.             if(even(exp_x)) x_per=PI/2.0;
  273.             else x_per=PI;
  274.             if(even(exp_y)) y_per=PI;
  275.             else y_per=2.0*PI;
  276.             if(even(exp_z)) z_per=PI;
  277.             else z_per=2.0*PI;
  278.             z_per /= a;
  279.             break;
  280.         case 5:
  281.             if (even(exp_x)) x_per=2.0*PI/a;
  282.             else x_per=PI/a;
  283.             if (even(exp_y)) y_per=2.0*PI/b;
  284.             else y_per=PI/b;
  285.             if (even(exp_z)) z_per=PI;
  286.             else z_per=2*PI;
  287.             break;
  288.     }
  289.     temp=lcm(x_per,y_per,z_per);
  290.     return(2*temp);
  291. } /* end algo_period */
  292.  
  293.  
  294. double lcm(double x, double y, double z)
  295. {
  296.     double val;
  297.  
  298.     val=x*y/gcd(x,y);
  299.     return(val*z/gcd(val,z));
  300. }
  301.  
  302.  
  303. double gcd(double a, double b)
  304. {
  305.     while (!equal(a,b)) {
  306.         if (a < b)
  307.             b -= a;
  308.         else a -= b;
  309.     }
  310.     return(a);
  311. }
  312.  
  313.  
  314. void ctds_output(struct queue_type queue[], const int num_sph, char *data[])
  315. {
  316.     struct pnode far *root=NULL;
  317.     char name[13],      /* name of data file            */
  318.          msg[80];       /* temp string                  */
  319.     FILE *stream;       /* the file handel              */
  320.  
  321.     struct max_vals val;    /* to track the highest and lowest x,y, and z coord */
  322.  
  323.     /* init some vars */
  324.     strcpy(name,"");                /* clear strings            */
  325.     val.xl=val.xh=queue[0].x;       /* init high/low trackers   */
  326.     val.yl=val.yh=queue[0].y;
  327.     val.zl=val.zh=queue[0].z;
  328.  
  329.     /* have user input the name of the data file to use         */
  330.     strcpy(name,input_name(".CTD"));
  331.     if (strlen(name) == 0) return;  /* bail out back to main menu   */
  332.  
  333.     root=ctds_sort(root, num_sph, algo_period(data));
  334.     /* open the data file */
  335.     if((stream=fopen(name,"wt")) == NULL)
  336.         error_fn(EFOPEN,name);
  337.     else {
  338.         /* write the data */
  339.         sprintf(msg,"Writing %s...",name);
  340.         disp_message(msg);
  341.         write_ctds_header(stream, name);
  342.         ftreeprint(stream, queue, root, atoi(data[SPH_RADIUS]), &val);
  343.         write_ctds_footer(stream, name, data, val);
  344.         if(fclose(stream)==EOF)
  345.             error_fn(EFCLOSE,name);
  346.         else {
  347.             sprintf(msg,"CTDS data file %s sucessfully written.  Any key to continue:",name);
  348.             disp_message(msg);
  349.             getch();
  350.         }
  351.     }
  352.     free_tree(root);
  353. } /* end ctds_output */
  354.  
  355.  
  356. struct pnode far *ctds_sort(struct pnode far *root, int num_sph, double period)
  357. {
  358.     int i;
  359.     double i_per;
  360.  
  361.     disp_message("Sorting data...");
  362.     for (i=0; i<num_sph; i++) {
  363.         i_per=(i/period)-floor(i/period);
  364.         root=tree(root, i, i_per);
  365.     }
  366.     return(root);
  367. }
  368.  
  369.  
  370. struct pnode far *tree(struct pnode far *p, int i, double i_per)
  371. {
  372.     char msg[40];
  373.     static unsigned long treecount;
  374.  
  375.     if (p==NULL) {                      /* new number */
  376.         if ((p = palloc()) == NULL) {   /* make a new node */
  377.             sprintf(msg,"tree calls: %u",treecount);
  378.             error_fn(EMEM,msg);
  379.         }
  380.         else treecount++;
  381.         p->n=i;
  382.         p->t=i_per;
  383.         p->left = p->right = NULL;
  384.     } 
  385.     else if (i_per < p->t)                /* if (i_per == p->t), then do nothing  */
  386.         p->left=tree(p->left, i, i_per);    /* because it is a repeated point       */
  387.     else if (i_per > p->t)
  388.         p->right=tree(p->right, i, i_per);
  389.     return(p);
  390. }
  391.  
  392.  
  393. /* free up the memmroy used by the binary tree */
  394. void free_tree(struct pnode far *p)
  395. {
  396.     if (p->left != NULL) 
  397.         free_tree(p->left);
  398.     if (p->right != NULL) 
  399.         free_tree(p->right);
  400.     free(p);
  401. }
  402.  
  403.  
  404. struct pnode far *palloc(void)
  405. {
  406. #ifdef DEBUG
  407.     char msg[40];
  408.  
  409.     debug=farcoreleft();
  410.     sprintf(msg,"free far core:  %lu",debug);
  411.     disp_message(msg);
  412. #endif
  413.  
  414.     return((struct pnode far *) farmalloc(sizeof(struct pnode)));
  415. }
  416.  
  417. /* either for CTDS output or CTDS sorted RAW output.  */
  418. void ftreeprint(FILE *stream, struct queue_type queue[],
  419.                struct pnode far *p, int r, struct max_vals *val)
  420. {
  421.     float x,y,z;
  422.  
  423.     if (p != NULL) {
  424.         ftreeprint(stream, queue, p->left, r, val);
  425.  
  426.         x=queue[p->n].x;
  427.         y=queue[p->n].y;
  428.         z=queue[p->n].z;
  429.         if (r == 0) {   /* for raw mode             */
  430.             fprintf(stream,"%11f  %11f  %11f\n",x,y,z);
  431.         }
  432.         else {
  433.             /* keep track of lowest and highest values */
  434.             if (x < val->xl) val->xl=x;
  435.             if (y < val->yl) val->yl=y;
  436.             if (z < val->zl) val->zl=z;
  437.             if (x > val->xh) val->xh=x;
  438.             if (y > val->yh) val->yh=y;
  439.             if (z > val->zh) val->zh=z;
  440.             fprintf(stream,"%10f  %10f  %10f  %2i\n",x,y,z,r);
  441.         }
  442.         ftreeprint(stream, queue, p->right, r, val);
  443.     }
  444. } /* end ftreeprint */
  445.  
  446. /* sort the array 'index' to the order in the binary tree 'p' */
  447. void sort_index(struct queue_type queue[], int index[],
  448.                 struct pnode far *p, int *count)
  449. {
  450.     if (p!=NULL) {
  451.         sort_index(queue, index, p->left, count);
  452.         index[(*count)++]=(p->n);
  453.         sort_index(queue, index, p->right, count);
  454.     }
  455. }
  456.  
  457.  
  458. void v_output(struct queue_type queue[], int index[], int num_sph, char *data[])
  459. {
  460.     char name[13],      /* name of data file            */
  461.          numcolors[3],  /* number of colors to use      */
  462.          msg[80];       /* temp string                  */
  463.     FILE *stream;       /* the file handel              */
  464.  
  465.     struct max_vals val;    /* to track the highest and lowest x,y, and z coord */
  466.  
  467.     /* init some vars */
  468.     strcpy(name,"");                /* clear strings            */
  469.     strcpy(numcolors,"");
  470.     val.xl=val.xh=queue[0].x;       /* init high/low trackers   */
  471.     val.yl=val.yh=queue[0].y;
  472.     val.zl=val.zh=queue[0].z;
  473.  
  474.     /* have user input the name of the data file to use         */
  475.     strcpy(name,input_name(".V"));
  476.     if (strlen(name) == 0) return;  /* bail out back to main menu   */
  477.  
  478.     /* now write out the data file */
  479.     if((stream=fopen(name,"wt")) == NULL)
  480.         error_fn(EFOPEN,name);
  481.     else {
  482.         sprintf(msg,"Writing %s...",name);
  483.         disp_message(msg);
  484.         write_v_header(stream, name, data[AXIS]);
  485.         write_v_spheres(stream, queue, index,
  486.                         atoi(data[SPH_RADIUS]), num_sph, &val);
  487.         write_v_footer(stream, name, data, val);
  488.         if(fclose(stream)==EOF)
  489.             error_fn(EFCLOSE,name);
  490.         else {
  491.             sprintf(msg,"Vivid data file %s sucessfully written.  Any key to continue:",name);
  492.             disp_message(msg);
  493.             getch();
  494.         }
  495.     }
  496. } /* end v_output */
  497.  
  498.  
  499. void smooth_v_output(struct queue_type queue[], int index[],
  500.                      int num_sph, char *data[])
  501. {
  502.     int  count=0;
  503.     char name[13],      /* name of data file            */
  504.          msg[80];       /* temp string                  */
  505.     FILE *stream;       /* the file handel              */
  506.     struct pnode far *root=NULL;    /* pointer to sorted spheres    */
  507.  
  508.     struct max_vals val;    /* to track the highest and lowest x,y, and z coord */
  509.  
  510.     /* init some vars */
  511.     strcpy(name,"");                /* clear strings            */
  512.     val.xl=val.xh=queue[0].x;       /* init high/low trackers   */
  513.     val.yl=val.yh=queue[0].y;
  514.     val.zl=val.zh=queue[0].z;
  515.  
  516.     /* have user input the name of the data file to use         */
  517.     strcpy(name,input_name(".V"));
  518.     if (strlen(name) == 0) return;  /* bail out back to main menu   */
  519.  
  520.     root=ctds_sort(root, num_sph, algo_period(data));
  521.  
  522.     /* now write out the data file */
  523.     if((stream=fopen(name,"wt")) == NULL)
  524.         error_fn(EFOPEN,name);
  525.     else {
  526.         sprintf(msg,"Writing %s...",name);
  527.         disp_message(msg);
  528.         write_v_header(stream, name, data[AXIS]);
  529.         sort_index(queue, index, root, &count);
  530.         write_smooth_v_spheres(stream, queue, index,
  531.                                atoi(data[SPH_RADIUS]), num_sph, &val);
  532.         write_v_footer(stream, name, data, val);
  533.         if(fclose(stream)==EOF)
  534.             error_fn(EFCLOSE,name);
  535.         else {
  536.             sprintf(msg,"Vivid data file %s sucessfully written.  Any key to continue:",name);
  537.             disp_message(msg);
  538.             getch();
  539.         }
  540.     }
  541.     free_tree(root);
  542. } /* end smooth_v_output */
  543.  
  544.  
  545. void write_smooth_v_spheres(FILE *stream, struct queue_type queue[], int index[],
  546.                            int radius, int num_sph, struct max_vals *val)
  547. {
  548.     int i,k;
  549.     float x, y, z,
  550.           x1, y1, z1;
  551.  
  552.     /* write one sphere and one connecting cylinder */
  553.     for (i=0; i<num_sph; i++) {
  554.         x=queue[index[i]].x;
  555.         y=queue[index[i]].y;
  556.         z=queue[index[i]].z;
  557.         k=i+1;
  558.         if (k >= num_sph) k=0;
  559.         x1=queue[index[k]].x;
  560.         y1=queue[index[k]].y;
  561.         z1=queue[index[k]].z;
  562.  
  563.         /* keep track of lowest and highest values */
  564.         if (x < val->xl) val->xl=x;
  565.         if (y < val->yl) val->yl=y;
  566.         if (z < val->zl) val->zl=z;
  567.         if (x > val->xh) val->xh=x;
  568.         if (y > val->yh) val->yh=y;
  569.         if (z > val->zh) val->zh=z;
  570.  
  571.         /* print a sphere and connector */
  572.         fprintf(stream,"sphere = { center = %f %f %f; radius = %i; }\n",x,y,z,radius);
  573.         fprintf(stream,"cone = { base = %f %f %f; base_radius = %i;\n",x,y,z,radius);
  574.         fprintf(stream,"         apex = %f %f %f; apex_radius = %i; }\n",x1,y1,z1,radius);
  575.     }
  576. } /* end write_smooth_v_spheres */
  577.  
  578.  
  579. void write_v_spheres(FILE *stream, struct queue_type queue[], int index[],
  580.                      int radius, int num_sph, struct max_vals *val)
  581. {
  582.     int i;
  583.     float x,y,z;
  584.  
  585.     /* write one sphere at a time */
  586.     for (i=0; i<num_sph; i++) {
  587.         x=queue[index[i]].x;
  588.         y=queue[index[i]].y;
  589.         z=queue[index[i]].z;
  590.  
  591.         /* keep track of lowest and highest values */
  592.         if (x < val->xl) val->xl=x;
  593.         if (y < val->yl) val->yl=y;
  594.         if (z < val->zl) val->zl=z;
  595.         if (x > val->xh) val->xh=x;
  596.         if (y > val->yh) val->yh=y;
  597.         if (z > val->zh) val->zh=z;
  598.  
  599.         /* print a sphere */
  600.         fprintf(stream,"sphere = { center = %f %f %f; radius = %i; }\n",x,y,z,radius);
  601.     }
  602. }
  603.  
  604.  
  605. void pv_output(struct queue_type queue[], int index[],
  606.                int num_sph, char *data[], int version)
  607. {
  608.     int col,            /* number of colors to be inputed                   */
  609.         actualcolors=0, /* number of colors actually inputed by user        */
  610.         i;              /* scratch loop variable        */
  611.     char name[13],      /* name of data file            */
  612.          numcolors[3],  /* number of colors to use      */
  613.          *output_color[MAX_OUTPUT_COLORS],  /* string of color definition   */
  614.          msg[80];       /* temp string                  */
  615.     FILE *stream;       /* the file handel              */
  616.  
  617.     struct max_vals val;    /* to track the highest and lowest x,y, and z coord */
  618.     extern struct field_struct field[];
  619.  
  620.     /* init some vars */
  621.     strcpy(name,"");                /* clear strings            */
  622.     strcpy(numcolors,"");
  623.     val.xl=val.xh=queue[0].x;       /* init high/low trackers   */
  624.     val.yl=val.yh=queue[0].y;
  625.     val.zl=val.zh=queue[0].z;
  626.     parm_field=FALSE;
  627.  
  628.     /* allocate space for user inputed color definitions */
  629.     for(i=0; i<MAX_OUTPUT_COLORS; i++) {
  630.         if ((output_color[i]=malloc(sizeof(char)*OUTPUT_COLOR_LEN)) == NULL)
  631.             error_fn(EMEM,"pv05_output");
  632.         strcpy(output_color[i],"");
  633.     }
  634.  
  635.     /* have user input the name of the data file to use         */
  636.     if (version == POV_VER_10)
  637.         strcpy(name,input_name(".POV"));
  638.     else strcpy(name,input_name(".DAT"));
  639.  
  640.     if (strlen(name) == 0) return;  /* bail out back to main menu   */
  641.  
  642.     /* input the number of colors to use and assign numercal value to 'col' */
  643.     erase_text(9,field[FILE_NAME].y,38);
  644.     sprintf(msg,"How may colors would you like to use? (MAX=%i) ",MAX_OUTPUT_COLORS);
  645.     disp_text(8,field[NUMCOLORS].y,msg,EGA_DARKGRAY);
  646.     fieldinput(NUMCOLORS,numcolors,"Press <ESC> to cancel",0);
  647.     col=atoi(numcolors);
  648.     if (col==0) return;
  649.     if (col > MAX_OUTPUT_COLORS) col=MAX_OUTPUT_COLORS;
  650.  
  651.     /* now input all the colors... */
  652.     for(i=0; i<col; i++) {
  653.         sprintf(msg,"declare Color%i = color ",i);
  654.         disp_text(8,field[COLOR_NAME].y+i,msg,EGA_DARKGRAY);
  655.         fieldinput(COLOR_NAME,output_color[i],"Press <ESC> to cancel",i);
  656.         if (!strcmp(output_color[i],"")) break;
  657.         actualcolors++;
  658.     }
  659.     if (actualcolors==0) {          /* a little error traping */
  660.         actualcolors=1;
  661.         strcpy(output_color[0],"CRed");
  662.     }
  663.  
  664.     /* now write out the data file in 'version' format */
  665.     if((stream=fopen(name,"wt")) == NULL)
  666.         error_fn(EFOPEN,name);
  667.     else {
  668.         sprintf(msg,"Writing %s ...",name);
  669.         disp_message(msg);
  670.         if (version==POV_VER_05) {
  671.             write_pv05_header(stream, name, actualcolors,
  672.                              output_color, atoi(data[SPH_RADIUS]), data[AXIS]);
  673.             write_pv05_spheres(stream, queue, index,
  674.                              actualcolors, num_sph, &val);
  675.             write_pv05_footer(stream, name, data, val);
  676.         }
  677.         else {
  678.             write_pv10_header(stream, name, actualcolors,
  679.                              output_color, atoi(data[SPH_RADIUS]), data[AXIS]);
  680.             write_pv10_spheres(stream, queue, index,
  681.                              actualcolors, num_sph, &val);
  682.             write_pv10_footer(stream, name, data, val);
  683.         }
  684.  
  685.         if(fclose(stream)==EOF)
  686.             error_fn(EFCLOSE,name);
  687.         else {
  688.             sprintf(msg,"PoV data file %s sucessfully written.  Any key to continue:",name);
  689.             disp_message(msg);
  690.             getch();
  691.         }
  692.     }
  693.  
  694.     /* do a little memmory clean-up */
  695.     for(i=0; i<MAX_OUTPUT_COLORS; i++) free(output_color[i]);
  696. } /* end pv05_output */
  697.  
  698.  
  699. void write_pv05_header(FILE *stream, char *name, int actualcolors,
  700.                      char *output_color[], int radius, char *axis)
  701. {
  702.     int i;
  703.     struct tm *tblock;
  704.     time_t timer;
  705.     char time_str[80];
  706.  
  707.     /* get the current time and date, so it can be put into data file */
  708.     timer = time(NULL);
  709.     tblock = localtime(&timer);
  710.     strcpy(time_str,asctime(tblock));
  711.  
  712.     /* Hit it! */
  713.     fprintf(stream,"{\n");
  714.     fprintf(stream,"  Lissajous figure PoV Ver. 0.5ß datafile %s\n", name);
  715.     fprintf(stream,"  Generated on %s  with LISSAJOU V %s\n",time_str,VERSION);
  716.     fprintf(stream,"  by Aaron C. Caba and Dan Farmer\n");
  717.     fprintf(stream,"}\n");
  718.     fprintf(stream,"\n");
  719.     fprintf(stream,"include \"shapes.dat\"\n");
  720.     fprintf(stream,"include \"colors.dat\"\n");
  721.     fprintf(stream,"include \"textures.dat\"\n");
  722.     fprintf(stream,"\n");
  723.     fprintf(stream,"declare Atexture = texture\n");
  724.     fprintf(stream,"  ambient 0.1 { same as textures.dat SHINY texture}\n");
  725.     fprintf(stream,"  diffuse 0.9\n");
  726.     fprintf(stream,"  phong 1.0\n");
  727.     fprintf(stream,"  phongsize 30.0\n");
  728.     fprintf(stream,"end_texture\n");
  729.     fprintf(stream,"\n");
  730.     fprintf(stream,"declare Sph_Radius = %i\n",radius);
  731.     fprintf(stream,"\n");
  732.     fprintf(stream,"view_point\n");
  733.     switch (axis[0]) {
  734.         case 'X':
  735.             fprintf(stream,"  location  <350.0  0.0  0.0> {modify as needed}\n");
  736.             fprintf(stream,"  direction < -1.0  0.0  0.0>\n");
  737.             fprintf(stream,"  up        <  0.0  0.0  1.0>\n");
  738.             fprintf(stream,"  right     <  0.0  1.3333  0.0>  /* right-handed! */\n");
  739.             break;
  740.         case 'Y':
  741.             fprintf(stream,"  location  <0.0  350.0  0.0> {modify as needed}\n");
  742.             fprintf(stream,"  direction <0.0   -1.0  0.0>\n");
  743.             fprintf(stream,"  up        <1.0    0.0  0.0>\n");
  744.             fprintf(stream,"  right     <0.0    0.0  1.3333>  /* right-handed! */\n");
  745.             break;
  746.         case 'Z':
  747.             fprintf(stream,"  location  <0.0  0.0   350.0> {modify as needed}\n");
  748.             fprintf(stream,"  direction <0.0  0.0    -1.0>\n");
  749.             fprintf(stream,"  up        <0.0  1.0     0.0>\n");
  750.             fprintf(stream,"  right     <1.3333  0.0  0.0>  /* right-handed! */\n");
  751.             break;
  752.     }
  753.     fprintf(stream,"  look_at   <0.0  0.0    0.0>\n");
  754.     fprintf(stream,"end_view_point\n");
  755.     fprintf(stream,"\n");
  756.     fprintf(stream,"{ basic light source }\n");
  757.     fprintf(stream,"object\n");
  758.     fprintf(stream,"  sphere <0.0  0.0  0.0>  2.0 end_sphere\n");
  759.     fprintf(stream,"  translate <300.0  300.0  300.0>\n");
  760.     fprintf(stream,"  colour red 1.0 green 1.0 blue 1.0\n");
  761.     fprintf(stream,"  light_source\n");
  762.     fprintf(stream,"  texture\n");
  763.     fprintf(stream,"    ambient 1.0\n");
  764.     fprintf(stream,"    diffuse 0.0\n");
  765.     fprintf(stream,"    color red 1.0 green 1.0 blue 1.0\n");
  766.     fprintf(stream,"  end_texture\n");
  767.     fprintf(stream,"end_object\n");
  768.     fprintf(stream,"\n");
  769.     fprintf(stream,"{ Put all colors into declarations for ease of changing }\n\n");
  770.  
  771.     /* print the user inputed color definitions */
  772.     for(i=0; i<actualcolors; i++) {
  773.         fprintf(stream,"declare Color%i = color %s\n",i,output_color[i]);
  774.     }
  775.     fprintf(stream,"\n");
  776.     fprintf(stream,"{ Here it is... }\n\n");
  777.     fprintf(stream,"composite\n\n");
  778. }
  779.  
  780.  
  781. void write_pv05_spheres(FILE *stream, struct queue_type queue[], int index[],
  782.                       int actualcolors, int num_sph, struct max_vals *val)
  783. {
  784.     int i;
  785.     float x,y,z;
  786.  
  787.     /* write one sphere at a time */
  788.     for (i=0; i<num_sph; i++) {
  789.         x=queue[index[i]].x;
  790.         y=queue[index[i]].y;
  791.         z=queue[index[i]].z;
  792.  
  793.         /* keep track of lowest and highest values */
  794.         if (x < val->xl) val->xl=x;
  795.         if (y < val->yl) val->yl=y;
  796.         if (z < val->zl) val->zl=z;
  797.  
  798.         if (x > val->xh) val->xh=x;
  799.         if (y > val->yh) val->yh=y;
  800.         if (z > val->zh) val->zh=z;
  801.  
  802.         fprintf(stream,"  object\n");
  803.         fprintf(stream,"    sphere <%f %f %f> Sph_Radius end_sphere\n",x,y,z);
  804.         fprintf(stream,"    color Color%i\n", i%actualcolors);
  805.         fprintf(stream,"    texture\n");
  806.         fprintf(stream,"      Atexture\n");
  807.         fprintf(stream,"      color Color%i\n", i%actualcolors);
  808.         fprintf(stream,"    end_texture\n");
  809.         fprintf(stream,"  end_object\n");
  810.         /* a kludge to fix PoV V0.5ß's problem with large size composites */
  811.         if ((i+1 % 25) == 0) {
  812.             fprintf(stream,"end_composite\n");
  813.             fprintf(stream,"composite\n");
  814.         }
  815.     }
  816. }
  817.  
  818.  
  819. void write_pv05_footer(FILE *stream, char *name,
  820.                        char *data[], struct max_vals val)
  821. {
  822.     fprintf(stream,"\n");
  823.     fprintf(stream,"end_composite\n");
  824.     fprintf(stream,"{\n");
  825.     write_stats(stream, "", data, val, atof(data[SPH_RADIUS]));
  826.     fprintf(stream,"}\n");
  827.     fprintf(stream,"{ *** End of %s *** }\n",name);
  828. }
  829.  
  830.  
  831. void write_pv10_header(FILE *stream, char *name, int actualcolors,
  832.                      char *output_color[], int radius, char *axis)
  833. {
  834.     int i;
  835.     struct tm *tblock;
  836.     time_t timer;
  837.     char time_str[80];
  838.  
  839.     /* get the current time and date, so it can be put into data file */
  840.     timer = time(NULL);
  841.     tblock = localtime(&timer);
  842.     strcpy(time_str,asctime(tblock));
  843.  
  844.     /* Hit it! */
  845.     fprintf(stream,"/*\n");
  846.     fprintf(stream,"  Lissajous figure PoV Ver. 1.0 datafile %s\n", name);
  847.     fprintf(stream,"  Generated on %s  with LISSAJOU V %s\n",time_str,VERSION);
  848.     fprintf(stream,"  by Aaron C. Caba and Dan Farmer\n");
  849.     fprintf(stream,"*/\n\n");
  850.     fprintf(stream,"#include \"shapes.inc\"\n");
  851.     fprintf(stream,"#include \"colors.inc\"\n");
  852.     fprintf(stream,"#include \"textures.inc\"\n\n");
  853.     fprintf(stream,"#declare Atexture = texture {\n");
  854.     fprintf(stream,"  ambient 0.1 \n");
  855.     fprintf(stream,"  diffuse 0.8\n");
  856.     fprintf(stream,"  phong 1.0\n");
  857.     fprintf(stream,"  phong_size 30.0\n");
  858.     fprintf(stream,"}\n\n");
  859.     fprintf(stream,"#declare Sph_Radius = %i\n\n",radius);
  860.     fprintf(stream,"camera { // modify as needed -- note right handed coords!\n");
  861.     switch (axis[0]) {
  862.         case 'X':
  863.             fprintf(stream,"  location  <350.0  0.0  0.0>\n");
  864.             fprintf(stream,"  direction < -1.0  0.0  0.0>\n");
  865.             fprintf(stream,"  up        <  0.0  0.0  1.0>\n");
  866.             fprintf(stream,"  right     <  0.0  1.3333  0.0>\n");
  867.             break;
  868.         case 'Y':
  869.             fprintf(stream,"  location  <0.0  350.0  0.0>\n");
  870.             fprintf(stream,"  direction <0.0   -1.0  0.0>\n");
  871.             fprintf(stream,"  up        <1.0    0.0  0.0>\n");
  872.             fprintf(stream,"  right     <0.0    0.0  1.3333>\n");
  873.             break;
  874.         case 'Z':
  875.             fprintf(stream,"  location  <0.0  0.0   350.0>\n");
  876.             fprintf(stream,"  direction <0.0  0.0    -1.0>\n");
  877.             fprintf(stream,"  up        <0.0  1.0     0.0>\n");
  878.             fprintf(stream,"  right     <1.3333  0.0  0.0>\n");
  879.             break;
  880.     }
  881.     fprintf(stream,"  look_at   <0.0  0.0     0.0>\n");
  882.     fprintf(stream,"}\n\n");
  883.     fprintf(stream,"// basic light source \n");
  884.     fprintf(stream,"object { light_source { <300 300 300> color White} }\n");
  885.     fprintf(stream,"\n");
  886.     fprintf(stream,"// Put all colors into declarations for ease of changing \n");
  887.     fprintf(stream,"\n");
  888.  
  889.     /* print the user inputed color definitions */
  890.     for(i=0; i<actualcolors; i++) {
  891.         fprintf(stream,"#declare Color%i = color %s\n",i,output_color[i]);
  892.     }
  893.     fprintf(stream,"\n");
  894.     fprintf(stream,"// Here it is... \n\n");
  895.     fprintf(stream,"composite {\n\n");
  896. } /* end write_pv10_header */
  897.  
  898.  
  899. void write_pv10_spheres(FILE *stream, struct queue_type queue[], int index[],
  900.                         int actualcolors, int num_sph, struct max_vals *val)
  901. {
  902.     int i;
  903.     float x,y,z;
  904.  
  905.     /* write one sphere at a time */
  906.     for (i=0; i<num_sph; i++) {
  907.         x=queue[index[i]].x;
  908.         y=queue[index[i]].y;
  909.         z=queue[index[i]].z;
  910.  
  911.         /* keep track of lowest and highest values */
  912.         if (x < val->xl) val->xl=x;
  913.         if (y < val->yl) val->yl=y;
  914.         if (z < val->zl) val->zl=z;
  915.  
  916.         if (x > val->xh) val->xh=x;
  917.         if (y > val->yh) val->yh=y;
  918.         if (z > val->zh) val->zh=z;
  919.  
  920.         fprintf(stream,"  object {\n");
  921.         fprintf(stream,"    sphere { <%f %f %f> Sph_Radius }\n",x,y,z);
  922.         fprintf(stream,"    color Color%i\n", i%actualcolors);
  923.         fprintf(stream,"    texture {\n");
  924.         fprintf(stream,"      Atexture\n");
  925.         fprintf(stream,"      color Color%i\n", i%actualcolors);
  926.         fprintf(stream,"    }\n");  /* end texture block */
  927.         fprintf(stream,"  }\n");    /* end object block */
  928.     }
  929. } /* end write_pv10_spheres */
  930.  
  931.  
  932. void write_pv10_footer(FILE *stream, char *name,
  933.                        char *data[], struct max_vals val)
  934. {
  935.     fprintf(stream,"} // end composite\n");           /* end composite */
  936.     fprintf(stream,"\n");
  937.     fprintf(stream,"/*\n");
  938.     write_stats(stream, "", data, val, atof(data[SPH_RADIUS]));
  939.     fprintf(stream,"*/\n");
  940.     fprintf(stream,"// *** End of %s *** \n",name);
  941. } /* end write_pv10_footer */
  942.  
  943.  
  944. void write_v_header(FILE *stream, char *name, char *axis)
  945. {
  946.     struct tm *tblock;
  947.     time_t timer;
  948.     char time_str[80];
  949.  
  950.     timer = time(NULL);
  951.     tblock = localtime(&timer);
  952.     strcpy(time_str,asctime(tblock));
  953.     fprintf(stream,"/*\n");
  954.     fprintf(stream,"  Lissajous figure Vivid datafile %s\n", name);
  955.     fprintf(stream,"  Generated on %s  with LISSAJOU V %s\n", time_str,VERSION);
  956.     fprintf(stream,"  by Aaron C. Caba and Dan Farmer\n");
  957.     fprintf(stream,"*/\n");
  958.     fprintf(stream,"\n");
  959.     fprintf(stream,"studio = {\n");
  960.     switch (axis[0]) {
  961.         case 'X':
  962.             fprintf(stream,"    from = 500.0 0.0 0.0;\n");
  963.             fprintf(stream,"    up   =   0.0 0.0 1.0;\n");
  964.             break;
  965.         case 'Y':
  966.             fprintf(stream,"    from = 0.0 500.0  0.0;\n");
  967.             fprintf(stream,"    up   = 1.0   0.0  0.0;\n");
  968.             break;
  969.         case 'Z':
  970.             fprintf(stream,"    from = 0.0 0.0 500.0;\n");
  971.             fprintf(stream,"    up   = 0.0 1.0    0.0;\n");
  972.             break;
  973.     }
  974.     fprintf(stream,"    at = 0.0  0.0  0.0;\n");
  975.     fprintf(stream,"    angle = 35;\n");
  976.     fprintf(stream,"    resolution = 320 200;\n");
  977.     fprintf(stream,"    aspect = 1.3333;\n");
  978. /*    fprintf(stream,"    bkg = black;\n"); */
  979.     fprintf(stream,"    ambient = .1 .1 .1;\n");
  980.     fprintf(stream,"}\n");
  981.     fprintf(stream,"\n");
  982.     fprintf(stream,"light = {\n");
  983.     fprintf(stream,"    type = point;\n");
  984.     fprintf(stream,"    falloff = 1;\n");
  985.     fprintf(stream,"    position = 300.0 300.0 300.0;\n");
  986.     fprintf(stream,"    color = 300 300 300;\n");
  987.     fprintf(stream,"}\n");
  988.     fprintf(stream,"\n");
  989.     fprintf(stream,"surface = {\n");
  990.     fprintf(stream,"    diffuse = 0.8 0.3 0.3;\n");
  991.     fprintf(stream,"    ambient = 0.1 0.1 0.1;\n");
  992.     fprintf(stream,"    shine = 50 0.5 0.5 0.5;\n");
  993.     fprintf(stream,"}\n");
  994.     fprintf(stream,"\n");
  995. } /* end write_v_header */
  996.  
  997.  
  998. void write_v_footer(FILE *stream, char *name, char *data[],
  999.                     struct max_vals val)
  1000. {
  1001.     fprintf(stream,"\n");
  1002.     fprintf(stream,"/*\n");
  1003.     write_stats(stream, "", data, val, atof(data[SPH_RADIUS]));
  1004.     fprintf(stream,"*/\n");
  1005.     fprintf(stream,"/* *** End of %s *** */\n",name);
  1006. } /* end write_v_footer */
  1007.  
  1008.  
  1009. void write_ctds_header(FILE *stream, char *name)
  1010. {
  1011.     struct tm *tblock;
  1012.     time_t timer;
  1013.     char time_str[80];
  1014.  
  1015.     timer=time(NULL);
  1016.     tblock = localtime(&timer);
  1017.     strcpy(time_str,asctime(tblock));
  1018.     fprintf(stream,";  Lissajous figure CTDS datafile %s\n", name);
  1019.     fprintf(stream,";  Generated on %s", time_str);
  1020.     fprintf(stream,";  with LISSAJOU Ver %s\n",VERSION);
  1021.     fprintf(stream,";  by Aaron C. Caba and Dan Farmer\n");
  1022.     fprintf(stream,";\n");
  1023.     fprintf(stream,";    X           Y           Z       R\n");
  1024. } /* end write_ctds_header */
  1025.  
  1026.  
  1027. void write_ctds_footer(FILE *stream, char *name,
  1028.                        char *data[], struct max_vals val)
  1029. {
  1030.     fprintf(stream,";\n");
  1031.     fprintf(stream,";\n");
  1032.     write_stats(stream, ";", data, val, atof(data[SPH_RADIUS]));
  1033.     fprintf(stream,";\n");
  1034.     fprintf(stream,"; *** End of %s *** ",name);
  1035. } /* end write_ctds_footer */
  1036.  
  1037.  
  1038. char *input_name(char *ext)
  1039. {
  1040.     char msg[30], name[13]="";
  1041.     extern struct field_struct field[];
  1042.  
  1043.     /* have user input the name of the data file to use         */
  1044.     sprintf(msg,"Name of output file: [%s]",ext);
  1045.     disp_text(9,field[FILE_NAME].y,msg,EGA_DARKGRAY);
  1046.     parm_field=FALSE;
  1047.     if ((fieldinput(FILE_NAME,name,"Press <ESC> to cancel",0) == '\x1B') || (!strcmp(name,"")))
  1048.         return("");
  1049.     strupr(name);
  1050.     strcat(name,ext);
  1051.     return(name);
  1052. } /* end input_name */
  1053.  
  1054.  
  1055. void write_stats(FILE *stream, char *prefix,
  1056.                  char *data[], struct max_vals val, float r)
  1057. {
  1058.     fprintf(stream,"%s  Parameters used for this generation:\n",prefix);
  1059.     fprintf(stream,"%s    R1 = %s   A = %s   B = %s\n",prefix,data[MAIN_RADIUS],data[A],data[B]);
  1060.     fprintf(stream,"%s    X-Exponent = %s\n",prefix,data[EXPONENT_X]);
  1061.     fprintf(stream,"%s    Y-Exponent = %s\n",prefix,data[EXPONENT_Y]);
  1062.     fprintf(stream,"%s    Z-Exponent = %s\n",prefix,data[EXPONENT_Z]);
  1063.     fprintf(stream,"%s    Sphere Radius = %s\n",prefix,data[SPH_RADIUS]);
  1064.     fprintf(stream,"%s    Number of Spheres generated:  %s\n",prefix,data[SPHERES]);
  1065.     fprintf(stream,"%s    Axis = %s\n",prefix,data[AXIS]);
  1066.     fprintf(stream,"%s    Algorithm = #%s\n",prefix,data[ALGO]);
  1067.     fprintf(stream,"%s\n",prefix);
  1068.     fprintf(stream,"%s    Minimum X = %f      Maximum X = %f\n", prefix, val.xl, val.xh);
  1069.     fprintf(stream,"%s    Minimum Y = %f      Maximum Y = %f\n", prefix, val.yl, val.yh);
  1070.     fprintf(stream,"%s    Minimum Z = %f      Maximum Z = %f\n", prefix, val.zl, val.zh);
  1071.     fprintf(stream,"%s\n",prefix);
  1072.     fprintf(stream,"%s    Min/Max XYZs with RADIUS figured in:\n",prefix);
  1073.     fprintf(stream,"%s    Leftmost Point = %f     Rightmost Point = %f\n", prefix, val.xl-r, val.xh+r);
  1074.     fprintf(stream,"%s      Lowest Point = %f       Highest Point = %f\n", prefix, val.yl-r, val.yh+r);
  1075.     fprintf(stream,"%s     Nearest Point = %f      Farthest Point = %f\n", prefix, val.zl-r, val.zh+r);
  1076. } /* end write_stats */
  1077.  
  1078. /* end-of-file output.c */
  1079.